package com.zhuangjie.shop.handler.activity;

import com.zhaungjie.base.utils.BigDecimalUtils;
import com.zhuangjie.mvc.future.ContextAwareExecutor;
import com.zhuangjie.order.entity.OrderActivity;
import com.zhuangjie.shop.entity.ShopActivityInstance;
import com.zhuangjie.shop.handler.activity.handler.ActivityHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 活动优惠结算器
 *
 * @author zhuangjie
 * @date 2024/03/15
 */

@Component
public class ActivityPreferentialSettlement {
    @Autowired
    private ContextAwareExecutor contextAwareExecutor;

    @Autowired
    private BigDecimalUtils bigDecimalUtils;

    /**
     * 处理器容器
     */
    private static Map<Long, ActivityHandler> handlerMap = new HashMap<>();

    /**
     * 扫描出定义的处理器
     */
    static {
        try {
            ClassLoader classLoader = ActivityPreferentialSettlement.class.getClassLoader();
            String packageName = ActivityPreferentialSettlement.class.getPackage().getName() + ".handler.impl";
            URL root = classLoader.getResource(packageName.replace(".", "/"));
            // 遍历文件夹下的所有文件
            File[] files = new File(root.getFile()).listFiles((dir, name) -> name.endsWith(".class"));

            List<Class> classes = new ArrayList<>();
            if (files != null) {
                for (File file : files) {
                    String className = file.getName().replaceAll(".class$", "");
                    classes.add(Class.forName(packageName + "." + className));

                }
            }
            for (Class aClass : classes) {
                Object instanceObj = aClass.newInstance();
                if (instanceObj instanceof ActivityHandler) {
                    ActivityHandler activityHandler = (ActivityHandler) instanceObj;
                    handlerMap.put(activityHandler.activityType().getCode(), activityHandler);
                }
            }
        } catch (Exception e) {
            // 当handler包下没有类时，会报错，不用理
        }
    }

    /**
     * 活动结算处理
     *
     * @param env                      用户相关环境信息（订单列表、与店铺距离、是否会员等）
     * @param shopActivityInstanceList 商店活动实例列表
     * @return {@link Map}<{@link ShopActivityInstance}, {@link BigDecimal}>
     */
    public List<OrderActivity> settlement(ActivityEnv env, Collection<ShopActivityInstance> shopActivityInstanceList) {
        List<OrderActivity> orderActivityList = new ArrayList<>();
        // 多线程计算活动能优惠的金额，如果优惠的金额不为空转为OrderActivity添加到orderActivityList
        CompletableFuture.allOf(shopActivityInstanceList.stream()
                .map(shopActivityInstance -> CompletableFuture.runAsync(() -> {
                    ActivityHandler activityHandler = handlerMap.get(shopActivityInstance.getActivityId());
                    // 找不到处理器
                    if (activityHandler == null) return;
                    BigDecimal activityDeductionAmount = activityHandler.calculateDiscounts(env, shopActivityInstance);
                    // 活动-不可优惠
                    if (activityDeductionAmount == null) return;
                    // 可优惠，组装为OrderActivity添加到orderActivityList
                    OrderActivity orderActivity = new OrderActivity();
                    orderActivity.setActivityInstanceId(shopActivityInstance.getId());
                    orderActivity.setActivityId(shopActivityInstance.getActivityId());
                    orderActivity.setActivityInstanceTitle(shopActivityInstance.getTitle());
                    orderActivity.setDeductionAmount(bigDecimalUtils.trimDecimalPlaces(activityDeductionAmount));
                    orderActivityList.add(orderActivity);
                },contextAwareExecutor)).toArray(CompletableFuture[]::new)).join();
        return orderActivityList;
    }

    /**
     * 检查活动instance的数据合法性
     */
    public static void checkActivityValid(ShopActivityInstance shopActivityInstance) {
        ActivityHandler activityHandler = handlerMap.get(shopActivityInstance.getActivityId());
        activityHandler.checkActivityValid(shopActivityInstance);
    }


}
